home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Diamond Collection
/
The Diamond Collection (Software Vault)(Digital Impact).ISO
/
cdr40
/
x1j4_src.zip
/
TNL7IP.C
< prev
next >
Wrap
Text File
|
1995-03-10
|
26KB
|
817 lines
/*****************************************************************************/
/* */
/* */
/* ***** ***** */
/* ***** ***** */
/* ***** ***** */
/* ***** ***** */
/* *************** *************** */
/* ***************** ***************** */
/* *************** *************** */
/* ***** ***** TheNet */
/* ***** ***** Portable. Compatible. */
/* ***** ***** Public Domain */
/* ***** ***** NORD><LINK */
/* */
/* This software is public domain ONLY for non commercial use */
/* */
/* */
/*****************************************************************************/
/* Level 7B IP switch commands */
/* Version 1 */
/* Dave Roberts G8KBB */
/* 10-April-1992 */
/* This software is written for the purposes of self-instruction in the
* subject of Amateur Radio. It is not complete or correct, it is not
* claimed that it works. It is not to be sold or to be used commercially
* or to be used in life critical or similar circumstances
*/
/*
* September 1993 - released as TheNet X-1J
*/
#include "all.h"
#include "tntyp.h" /* Definition der Typen */
#include "tnl7be.h"
#include "ip.h"
#include "icmp.h"
#define EXTERN extern
#include "ipv.h"
/* The following structures are used to display information
* from the iproute and arp commands
*/
char *if_modes[] = { " ", "DG", "VC" };
char *if_names[] = { "Net/Rom", "Port 0", "Port 1" };
/* ***************************************************************************
* Function : ccpipr - The IProute command
*
* Inputs : none explicitly. Reads globals of clicnt and clipoi
*
* Outputs : an updated route table and a display to the user
*
* Operation : Management of the ip routes table
* -------------------------------------------------------------------------*/
VOID ccpipr()
{
ipaddr host, gateway;
unsigned bits, metric;
signed port;
register mhtyp *bufpoi;
register IP_ROUTE_MB *iprmb;
char *clipoitmp;
register unsigned i = 1;
bits = 32;
host.Short[1] = host.Short[0] = gateway.Short[1] =
gateway.Short[0] = metric = 0;
/* first, if no parameters are given, drop thru to display
*/
if( clicnt > 0 )
{
/* a valid address must be the first parameter,
* followed optionally by the number of bits
*/
if( get_ip_addr( &host, &clicnt, &clipoi ) )
{
i = 0;
if( skipspace() )
{
if( *clipoi == '/' )
{
nxtcli();
if( (bits = nextnumber() ) > 32 )
goto no_change_route;
}
/* the sysop only commands are '+' and '-'
*/
if( issyso() )
{
switch( *clipoi )
{
case '-':
rt_drop( &host, bits );
break;
case '+':
nxtcli();
if( skipspace() )
{
if( upcase( *clipoi ) == 'N' )
port = 0;
else if(*clipoi >='0' && *clipoi < NUMPORTS+'0')
port = *clipoi - '0'+1;
else
goto no_change_route;
i = clicnt;
clipoitmp = clipoi;
if( skipnext( &clicnt, &clipoi ) )
if( !get_ip_addr( &gateway, &clicnt, &clipoi ) )
{
clipoi = clipoitmp;
clicnt = i;
}
if( skipnext( &clicnt, &clipoi ) )
metric = nextnumber();
rt_add( &host, bits, &gateway, port, metric, 0, 0 );
}
}
}
}
}
}
no_change_route:
#ifdef USELONG
host.Long &= ~0L << ( 32-bits );
#else
ip_mask( &host, bits );
#endif
bufpoi = putals("\015Destination Len I/F Gateway Metric");
for( iprmb = (IP_ROUTE_MB *)IP_Routes.lnext;
iprmb != (IP_ROUTE_MB *)&IP_Routes.lnext;
iprmb = (IP_ROUTE_MB *)iprmb->link.lnext )
if( i )
showroute( &iprmb->route, bufpoi );
#ifdef USELONG
else if(host.Long == iprmb->route.dest.Long && bits == iprmb->route.bits)
#else
else if(host.Short[0] == iprmb->route.dest.Short[0] &&
host.Short[1] == iprmb->route.dest.Short[1] &&
bits == iprmb->route.bits)
#endif
{
showroute( &iprmb->route, bufpoi );
break;
}
seteom( bufpoi );
}
/* ***************************************************************************
* Function : display a single route entry in ip route table
*
* Inputs : pointer into route table and output buffer pointer
*
* Outputs : no return value
*
* Operation : take route table entry, convert to ascii & put in buffer
* -------------------------------------------------------------------------*/
VOID showroute( rp, bufpoi )
register IP_ROUTE *rp;
register mhtyp *bufpoi;
{
putchr( '\015', bufpoi );
bufpoi->l4time = bufpoi->putcnt; /* mark position */
show_ip_addr( &rp->dest, bufpoi ); /* display address */
putspa( 18, bufpoi ); /* tab in to 18 */
putnum( rp->bits, bufpoi ); /* disp bits value */
putspa( 22, bufpoi ); /* tab in again */
putstr( if_names[rp->interface], bufpoi ); /* show port */
putspa( 30, bufpoi ); /* tab in to 30 */
#ifdef USELONG /* if gateway set,..*/
if( rp->gateway.Long != 0 )
#else
if( rp->gateway.Short[0] != 0 || rp->gateway.Short[1] != 0 )
#endif
show_ip_addr( &rp->gateway, bufpoi ); /* display gateway */
putspa( 48, bufpoi ); /* tab in to 40 */
if( rp->metric != 0 ) /* if metric set, */
putnum( rp->metric, bufpoi ); /* show metric */
return;
}
/* ***************************************************************************
* Function : show an ip address as ascii
*
* Inputs : a pointer to an address and a pointer to an o/p buffer
*
* Outputs : no return value
*
* Operation : take each byte in turn, and convert to hex with '.' between
* -------------------------------------------------------------------------*/
VOID show_ip_addr( address, bufpoi )
register ipaddr *address;
register mhtyp *bufpoi;
{
register int i;
for( i=3; i >= 0 ; i-- )
{
putnum( address->Bytes[i], bufpoi );
if( i )
putchr( '.', bufpoi );
}
}
/* ***************************************************************************
* Function : get an ip address from input buffer
*
* Inputs : pointer to o/p ip address buffer, clicnt & clipoi
*
* Outputs : return 0 if syntax error, 1 if converted OK
*
* Operation : extract in sequence, 4 numbers & 3 'dots' nnn.nnn.nnn.nnn
* -------------------------------------------------------------------------*/
get_ip_addr( target, count, ptr )
ipaddr *target;
register signed *count;
register char **ptr;
{
unsigned addr[4];
register signed int i;
for( i=0; i<4; i++ )
{
if( ( addr[i] = nxtnum( count, ptr ) ) > 255 )
return( FALSE );
if( i < 3 )
{
if( *count < 1 || **ptr != '.' )
return( FALSE );
else
{
(*ptr)++;
(*count)--;
}
}
}
for( i=3; i>=0; i-- )
target->Bytes[i] = addr[3-i];
return( TRUE );
}
/* ***************************************************************************
* Function : Command line interpreter for arp table changes/display
*
* Inputs : no parameters, reads clicnt, clipoi & arp table
*
* Outputs : no return value. Updates table.
*
* Operation : add entry if requested, show new entry or whole table
* -------------------------------------------------------------------------*/
VOID ccparp()
{
ipaddr host;
char hwtype, dgmode;
register unsigned i;
register mhtyp *bufpoi;
register ARP_TAB_MB *arpmb;
char call[7];
unsigned publish;
char c;
host.Short[1] = host.Short[0] = publish = 0;
/* if a parameter is passed, try to parse command line
* otherwise just drop into whole table display.
* the syntax is, initially, an address followed by '-' or '+'
* but only the sysop may add or delete !
*/
if( clicnt > 0 )
{
if( get_ip_addr( &host, &clicnt, &clipoi ) )
{
if( issyso() )
{
switch( *clipoi )
{
case '-':
nxtcli();
if( skipspace() )
{
switch( upcase( *clipoi ) )
{
case 'N':
hwtype = ARP_NETROM;
break;
case 'A':
hwtype = ARP_AX25;
break;
default:
goto no_change_arp;
}
arp_drop( &host, hwtype );
}
break;
case '+':
nxtcli();
if( skipspace() && upcase(*clipoi)=='P')
{
nxtcli();
publish = 1;
}
if( skipspace() )
{
switch( upcase( *clipoi ) )
{
case 'N':
hwtype = ARP_NETROM;
break;
case 'A':
hwtype = ARP_AX25;
break;
default:
goto no_change_arp;
}
/* We have address, '+' and subnet type, now
* we need a hardware address ( ie a callsign )
* and optionally a mode ( dg/vc )
*/
skipnext( &clicnt, &clipoi );
if( !getcal( &clicnt, &clipoi, 1, call ) )
goto no_change_arp;
if( skipspace() &&
(c=upcase(*clipoi)) == 'D' )
dgmode = 1;
else if( c == 'V' )
dgmode = 2;
else
dgmode = 0;
arp_add( &host, hwtype, call, dgmode, 0, publish );
}
}
}
}
}
no_change_arp:
bufpoi = putals("\015Destination P hw-type Callsign Mode Timer");
#ifdef USELONG
i = ( host.Long == 0 );
#else
i = ( host.Short[0] == 0 && host.Short[1] == 0 );
#endif
for( arpmb = (ARP_TAB_MB *)Arp_tab.lnext;
arpmb != (ARP_TAB_MB *)&Arp_tab.lnext;
arpmb = (ARP_TAB_MB *)arpmb->link.lnext )
if( ( i != 0 ) ||
#ifdef USELONG
(host.Long == arpmb->arp.dest.Long ) )
#else
(host.Short[0] == arpmb->arp.dest.Short[0] &&
host.Short[1] == arpmb->arp.dest.Short[1] ) )
#endif
showarp( &arpmb->arp, bufpoi );
seteom( bufpoi );
}
/* ***************************************************************************
* Function : showarp()
*
* Inputs : pointer to an arp table entry and a message buffer pointer
*
* Outputs : no return value. Text added to bufpoi for arp entry
*
* Operation : create text version of arp entry & put into buffer
* -------------------------------------------------------------------------*/
VOID showarp( arp, bufpoi )
register ARP_TAB *arp;
register mhtyp *bufpoi;
{
putchr( '\015', bufpoi );
bufpoi->l4time = bufpoi->putcnt;
show_ip_addr( &arp->dest, bufpoi );
putspa( 18, bufpoi );
putstr( ( arp->publish_flag ? "P " : " " ), bufpoi );
putstr( ( arp->hwtype ? "AX.25" : if_names[0] ) , bufpoi );
putspa( 28, bufpoi );
putid( arp->callsign, bufpoi );
putspa( 40, bufpoi );
putstr( if_modes[ arp->dgmode & 3 ], bufpoi );
if( arp->timer != 0 )
{
putspa( 46, bufpoi );
putnum( arp->timer, bufpoi );
}
}
/* ***************************************************************************
* Function : ccpipa() - the node ip address command line interpreter
*
* Inputs : no parameters. reads clicnt, clipoi & my_ip_address
*
* Outputs : no return value. Updates my_ip_address & shows it in bufpoi
*
* Operation : if sysop & if new addr given update ip address. Display it
* -------------------------------------------------------------------------*/
VOID ccpipa()
{
ccp_ip_help( &my_ip_addr, "My" );
}
VOID ccp_ip_help( ip_addr, name )
register ipaddr *ip_addr;
char *name;
{
register mhtyp *bufpoi;
if( issyso() )
get_ip_addr( ip_addr, &clicnt, &clipoi );
bufpoi = putals( name );
putstr( " IP address : ", bufpoi );
show_ip_addr( ip_addr, bufpoi );
seteom( bufpoi );
}
/* ***************************************************************************
* Function : ccpipb() - the node ip b'cast address command line interpreter
*
* Inputs : no parameters. reads clicnt, clipoi & bcast_ip_address
*
* Outputs : no return value. Updates bcast_ip_address & shows it in bufpoi
*
* Operation : if sysop & if new addr given update ip address. Display it
* -------------------------------------------------------------------------*/
VOID ccpipb()
{
ccp_ip_help( &bcast_ip_addr, "Broadcast" );
}
/* ***********************************************************************
* This is the parameter table for the ip router.
* The first entry controls the port default L2 modes
* The rest is the IP MIB
* It is structured as per PARMS etc to allow re-use of common code
*/
partyp iptab[] = {
&Ip_mib[0].value.integer, 0, MAXPORTMASK,
&Ip_mib[1].value.integer, 0, 1,
&Ip_mib[2].value.integer, 2, MAXTTL,
&Ip_mib[3].value.integer, 0, 0,
&Ip_mib[4].value.integer, 0, 0,
&Ip_mib[5].value.integer, 0, 0,
&Ip_mib[6].value.integer, 0, 0,
&Ip_mib[7].value.integer, 0, 0,
&Ip_mib[8].value.integer, 0, 0,
&Ip_mib[9].value.integer, 0, 0,
&Ip_mib[10].value.integer, 0, 0,
&Ip_mib[11].value.integer, 0, 0,
&Ip_mib[12].value.integer, 0, 0,
&Ip_mib[13].value.integer, 1, 65535,
&Ip_mib[14].value.integer, 0, 0,
&Ip_mib[15].value.integer, 0, 0,
&Ip_mib[16].value.integer, 0, 0,
&Ip_mib[17].value.integer, 0, 0,
&Ip_mib[18].value.integer, 0, 0,
&Ip_mib[19].value.integer, 0, 0
};
/* ***************************************************************************
* Function : ccpips() - the ip stats parameters command
*
* Inputs : none - reads IP MIB passes it on to ccp_par()
*
* Outputs : as per ccp_par
*
* Operation : updates and / or displays IP MIB data
* -------------------------------------------------------------------------*/
VOID ccpips()
{
ccp_par( iptab, ( sizeof( iptab ) / sizeof( struct param ) ) );
}
/* ***************************************************************************
* Function : ccpart() - the arp control parameters command
*
* Inputs : none - passes table details on to ccp_par
*
* Outputs : as per ccp_par
*
* Operation : updates and / or displays ARP data
* -------------------------------------------------------------------------*/
partyp arptab[] =
{
&ARPrunning, 0, 1,
&ARPtimer, 15, 24*60
};
VOID ccpart()
{
ccp_par( arptab, ( sizeof( arptab ) / sizeof( struct param ) ) );
}
/* ***********************************************************************
* as per iptab, this is the ICMP MIB. It is not currently used
*/
#ifdef ICMPSTATS
partyp icmptab[] = {
&Icmp_mib[1].value.integer, 0, 0,
&Icmp_mib[2].value.integer, 0, 0,
&Icmp_mib[3].value.integer, 0, 0,
&Icmp_mib[4].value.integer, 0, 0,
&Icmp_mib[5].value.integer, 0, 0,
&Icmp_mib[6].value.integer, 0, 0,
&Icmp_mib[7].value.integer, 0, 0,
&Icmp_mib[8].value.integer, 0, 0,
&Icmp_mib[9].value.integer, 0, 0,
&Icmp_mib[10].value.integer, 0, 0,
&Icmp_mib[11].value.integer, 0, 0,
&Icmp_mib[12].value.integer, 0, 0,
&Icmp_mib[13].value.integer, 0, 0,
&Icmp_mib[14].value.integer, 0, 0,
&Icmp_mib[15].value.integer, 0, 0,
&Icmp_mib[16].value.integer, 0, 0,
&Icmp_mib[17].value.integer, 0, 0,
&Icmp_mib[18].value.integer, 0, 0,
&Icmp_mib[19].value.integer, 0, 0,
&Icmp_mib[20].value.integer, 0, 0,
&Icmp_mib[21].value.integer, 0, 0,
&Icmp_mib[22].value.integer, 0, 0,
&Icmp_mib[23].value.integer, 0, 0,
&Icmp_mib[24].value.integer, 0, 0,
&Icmp_mib[25].value.integer, 0, 0,
&Icmp_mib[26].value.integer, 0, 0
};
/* ***************************************************************************
* Function : ccpics() - the icmp stats parameters command
*
* Inputs : none - reads ICMP MIB passes it on to ccp_par()
*
* Outputs : as per ccp_par
*
* Operation : updates and / or displays ICMP MIB data
* -------------------------------------------------------------------------*/
VOID ccpics()
{
ccp_par( icmptab, ( sizeof( icmptab ) / sizeof( struct param ) ) );
}
#endif
/* ***************************************************************************
* Function : rt_add
*
* Inputs : pointer to host address
* number of significant bits in address
* pointer to gateway address ( if zero, no gateway )
* port number ( order as per interfaces structure )
* metric
* time to live in seconds before route entry explodes
* flag to say if this route is private
*
* Returns : true / false return on whether route table updated
* updates routing table
*
* Operation : add route to routing table, or update if already there
* -------------------------------------------------------------------------*/
rt_add( target, bits, gateway, iface, metric, ttl, private )
ipaddr *target;
unsigned bits;
ipaddr *gateway;
signed iface;
unsigned metric;
unsigned ttl;
BOOLEAN private;
{
IP_ROUTE_MB *iprp;
register IP_ROUTE_MB *iprp2;
ipaddr temp;
if( !route_find( &iprp, &temp, target, bits ) )
{
iprp2 = (IP_ROUTE_MB *)allocb();
relink( iprp2, iprp->link.lprev );
iprp = iprp2;
}
iprp2 = iprp;
#ifdef USELONG
iprp2->route.dest.Long = temp.Long;
iprp2->route.gateway.Long = gateway->Long;
#else
iprp2->route.dest.Short[0] = temp.Short[0];
iprp2->route.dest.Short[1] = temp.Short[1];
iprp2->route.gateway.Short[0] = gateway->Short[0];
iprp2->route.gateway.Short[1] = gateway->Short[1];
#endif
iprp2->route.bits = bits;
iprp2->route.interface = iface;
iprp2->route.metric = metric;
iprp2->route.timer = ttl;
iprp2->route.flags = private ? RTPRIVATE : 0 ;
return( TRUE );
}
/* ***************************************************************************
* Function : route_find() - locates ip route table entry for given address
*
* Inputs : pointer to pointer to result, ptr to masked ( real ) result,
* pointer to desired target ip address & number if IP addr bits
*
* Returns : boolean result, masked value of address in temp and pointer
* to ip route table entry in iprptr
*
* Operation : look for a match of (bits) bits to address (target) in the
* ip route table. Give Boolean result & pointer to the entry
* -------------------------------------------------------------------------*/
route_find( iprptr, temp, target, bits )
IP_ROUTE_MB **iprptr;
register ipaddr *temp;
ipaddr *target;
register unsigned bits;
{
register IP_ROUTE_MB *iprp;
#ifdef USELONG
temp->Long = target->Long;
#else
temp->Short[0] = target->Short[0];
temp->Short[1] = target->Short[1];
#endif
if( bits > 32 )
bits = 32;
#ifdef USELONG
temp->Long &= ~0L << 32-bits;
#else
ip_mask( temp, bits );
#endif
IP_Route_Cache.route = NULLROUTE;
for( iprp = (IP_ROUTE_MB *)IP_Routes.lnext;
iprp != (IP_ROUTE_MB *)&IP_Routes.lnext && bits <= iprp->route.bits;
iprp = (IP_ROUTE_MB *)iprp->link.lnext )
#ifdef USELONG
if( iprp->route.dest.Long == temp->Long && iprp->route.bits == bits )
#else
if( iprp->route.dest.Short[0] == temp->Short[0] &&
iprp->route.dest.Short[1] == temp->Short[1] &&
iprp->route.bits == bits )
#endif
{
*iprptr = iprp;
return( TRUE );
}
*iprptr = iprp;
return( FALSE );
}
/* ***************************************************************************
* Function : rt_drop() - delete an entry in the ip route table
*
* Inputs : ip address pointer and number of bits significance
*
* Returns : boolean result. Also updates the ip route table
*
* Operation : look for target in ip route table. Delete if found.
* -------------------------------------------------------------------------*/
rt_drop( target, bits )
ipaddr *target;
unsigned bits;
{
IP_ROUTE_MB *iprp;
ipaddr temp;
if( route_find( &iprp, &temp, target, bits ) )
{
dealoc( unlink( iprp ) );
return( TRUE );
}
return( FALSE );
}
/* ***************************************************************************
* Function : arp_add() - make an entry in the arp table
*
* Inputs : IP address, hardware type, hardware address( callsign),
* datagram mode flag, time to live and published entry flag
*
* Returns : boolean result of success / failure of operation
* currently, it *can* only succeed !
*
* Operation : find existing entry & update it or make a new entry
* in the arp table.
* IMPORTANT - the table is not arranged as a set of tables
* for each bit length. Rather it is stored in descending
* order of significant bits.
* -------------------------------------------------------------------------*/
arp_add( target, hwtype, callsign, dgmode, ttl, publish )
register ipaddr *target;
char *callsign;
BOOLEAN dgmode;
unsigned ttl, hwtype;
BOOLEAN publish;
{
ARP_TAB_MB *arprp;
register ARP_TAB_MB *arprp2;
if( !find_arp( &arprp, target, hwtype ) )
{
arprp = (ARP_TAB_MB *)allocb();
relink( arprp, Arp_tab.lnext );
}
arprp2 = arprp;
#ifdef USELONG
arprp2->arp.dest.Long = target->Long;
#else
arprp2->arp.dest.Short[0] = target->Short[0];
arprp2->arp.dest.Short[1] = target->Short[1];
#endif
arprp2->arp.hwtype = hwtype;
arprp2->arp.timer = ttl;
arprp2->arp.publish_flag = publish;
arprp2->arp.dgmode = dgmode;
cpyid( arprp2->arp.callsign, callsign );
return( TRUE );
}
/* ***************************************************************************
* Function : find_arp() - tell me the hardware address for an IP address
*
* Inputs : pointer to result, desired IP address and hardware type
*
* Returns : boolean result & pointer to entry in arpptr
*
* Operation : scan the arp table for a match for the target address
* for a given hardware address. If found, point to address
* and say it succeeded.
* -------------------------------------------------------------------------*/
find_arp( arpptr, target, hwtype )
ARP_TAB_MB **arpptr;
ipaddr *target;
unsigned hwtype;
{
register ARP_TAB_MB *arprp;
for( arprp = (ARP_TAB_MB *)Arp_tab.lnext;
arprp != (ARP_TAB_MB *)&Arp_tab.lnext;
arprp = (ARP_TAB_MB *)arprp->link.lnext )
#ifdef USELONG
if( (arprp->arp.dest.Long == target->Long) &&
(hwtype == arprp->arp.hwtype) )
#else
if( arprp->arp.dest.Short[0] == target->Short[0] &&
arprp->arp.dest.Short[1] == target->Short[1] &&
(hwtype == arprp->arp.hwtype) )
#endif
{
*arpptr = arprp;
return( TRUE );
}
return( FALSE );
}
/* ***************************************************************************
* Function : arp_drop() - delete an entry in the arp table
*
* Inputs : desired ip addess & number of bits
*
* Returns : boolean on result. Updates arp table
*
* Operation : Find arp table match. Delete it if found. Tell me so.
* -------------------------------------------------------------------------*/
arp_drop( target, hwtype )
ipaddr *target;
unsigned hwtype;
{
ARP_TAB_MB *arprp;
if( find_arp( &arprp, target, hwtype ) )
{
dealoc( unlink( arprp ) );
return( TRUE );
}
return( FALSE );
}
/*- End of IP router switch commands ---------------------------------------*/
/*- start of IP router timer service routine--------------------------------*/
arpsrv()
{
register ARP_TAB_MB *arprp;
register ARP_TAB_MB *arp;
if( ARPrunning && --ARPcounter == 0 )
{
ARPcounter = 60;
for( arprp = (ARP_TAB_MB *)Arp_tab.lnext;
arprp != (ARP_TAB_MB *)&Arp_tab.lnext;
)
{
arp = arprp;
arprp = (ARP_TAB_MB *)arprp->link.lnext;
if( arp->arp.timer != 0 && --arp->arp.timer == 0 )
arp_drop( &arp->arp.dest, arp->arp.hwtype );
}
}
}
/*- end of IP router timer service routine----------------------------------*/